/**
* Copyright (c) 2013 Obeo.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Obeo - initial API and implementation
*/
package org.eclipselabs.emf.loophole.ui.internal.model.editor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.codegen.ecore.CodeGenEcorePlugin;
import org.eclipse.emf.codegen.ecore.generator.Generator;
import org.eclipse.emf.codegen.ecore.genmodel.GenBase;
import org.eclipse.emf.codegen.ecore.genmodel.GenModel;
import org.eclipse.emf.codegen.ecore.genmodel.generator.GenBaseGeneratorAdapter;
import org.eclipse.emf.codegen.ecore.genmodel.provider.GenModelEditPlugin;
import org.eclipse.emf.common.ui.viewer.IViewerProvider;
import org.eclipse.emf.edit.ui.action.ControlAction;
import org.eclipse.emf.edit.ui.action.EditingDomainActionBarContributor;
import org.eclipse.emf.edit.ui.action.LoadResourceAction;
import org.eclipse.emf.edit.ui.action.ValidateAction;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IContributionManager;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.SubContributionItem;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipselabs.emf.loophole.internal.model.GenGapModel;
import org.eclipselabs.emf.loophole.internal.model.GenGapPackage;
import org.eclipselabs.emf.loophole.ui.internal.LoopholeUIPlugin;
/**
* This is the action bar contributor for the Loophole model editor.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public class LoopholeActionBarContributor
extends EditingDomainActionBarContributor
implements ISelectionChangedListener {
/**
* This keeps track of the active editor.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected IEditorPart activeEditorPart;
/**
* This keeps track of the current selection provider.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected ISelectionProvider selectionProvider;
/**
* This action opens the Properties view.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected IAction showPropertiesViewAction =
new Action(LoopholeUIPlugin.INSTANCE.getString("_UI_ShowPropertiesView_menu_item")) //$NON-NLS-1$
{
@Override
public void run() {
try {
getPage().showView("org.eclipse.ui.views.PropertySheet"); //$NON-NLS-1$
}
catch (PartInitException exception) {
LoopholeUIPlugin.INSTANCE.log(exception);
}
}
};
/**
* This action refreshes the viewer of the current editor if the editor
* implements {@link org.eclipse.emf.common.ui.viewer.IViewerProvider}.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected IAction refreshViewerAction =
new Action(LoopholeUIPlugin.INSTANCE.getString("_UI_RefreshViewer_menu_item")) //$NON-NLS-1$
{
@Override
public boolean isEnabled() {
return activeEditorPart instanceof IViewerProvider;
}
@Override
public void run() {
if (activeEditorPart instanceof IViewerProvider) {
Viewer viewer = ((IViewerProvider)activeEditorPart).getViewer();
if (viewer != null) {
viewer.refresh();
}
}
}
};
/**
* This will contain one {@link org.eclipse.emf.edit.ui.action.CreateChildAction} corresponding to each descriptor
* generated for the current selection by the item provider.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected Collection<IAction> createChildActions;
/**
* This is the menu manager into which menu contribution items should be added for CreateChild actions.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected IMenuManager createChildMenuManager;
/**
* This will contain one {@link org.eclipse.emf.edit.ui.action.CreateSiblingAction} corresponding to each descriptor
* generated for the current selection by the item provider.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected Collection<IAction> createSiblingActions;
/**
* This is the menu manager into which menu contribution items should be added for CreateSibling actions.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected IMenuManager createSiblingMenuManager;
/**
* This creates an instance of the contributor.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public LoopholeActionBarContributor() {
super(ADDITIONS_LAST_STYLE);
loadResourceAction = new LoadResourceAction();
validateAction = new ValidateAction();
controlAction = new ControlAction();
}
/**
* This adds Separators for editor additions to the tool bar.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void contributeToToolBar(IToolBarManager toolBarManager) {
toolBarManager.add(new Separator("loophole-settings")); //$NON-NLS-1$
toolBarManager.add(new Separator("loophole-additions")); //$NON-NLS-1$
}
/**
* This adds to the menu bar a menu and some separators for editor additions,
* as well as the sub-menus for object creation items.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void contributeToMenu(IMenuManager menuManager) {
super.contributeToMenu(menuManager);
generateMenuManager =
new MenuManager(GenModelEditPlugin.INSTANCE.getString("_UI_Generate_menu"), "org.eclipse.emf.codegen.ecore.genmodelMenuID");
menuManager.insertAfter("additions", generateMenuManager);
generateMenuManager.add(generateModelAction);
generateMenuManager.add(generateEditAction);
generateMenuManager.add(generateEditorAction);
generateMenuManager.add(generateTestsAction);
generateMenuManager.add(generateAllAction);
IMenuManager submenuManager = new MenuManager(LoopholeUIPlugin.INSTANCE.getString("_UI_LoopholeEditor_menu"), "org.eclipselabs.emf.loophole.internal.modelMenuID"); //$NON-NLS-1$ //$NON-NLS-2$
menuManager.insertAfter("additions", submenuManager); //$NON-NLS-1$
submenuManager.add(new Separator("settings")); //$NON-NLS-1$
submenuManager.add(new Separator("actions")); //$NON-NLS-1$
submenuManager.add(new Separator("additions")); //$NON-NLS-1$
submenuManager.add(new Separator("additions-end")); //$NON-NLS-1$
// Prepare for CreateChild item addition or removal.
//
createChildMenuManager = new MenuManager(LoopholeUIPlugin.INSTANCE.getString("_UI_CreateChild_menu_item")); //$NON-NLS-1$
submenuManager.insertBefore("additions", createChildMenuManager); //$NON-NLS-1$
// Prepare for CreateSibling item addition or removal.
//
createSiblingMenuManager = new MenuManager(LoopholeUIPlugin.INSTANCE.getString("_UI_CreateSibling_menu_item")); //$NON-NLS-1$
submenuManager.insertBefore("additions", createSiblingMenuManager); //$NON-NLS-1$
// Force an update because Eclipse hides empty menus now.
//
submenuManager.addMenuListener
(new IMenuListener() {
public void menuAboutToShow(IMenuManager menuManager) {
menuManager.updateAll(true);
}
});
addGlobalActions(submenuManager);
}
/**
* When the active editor changes, this remembers the change and registers with it as a selection provider.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void setActiveEditor(IEditorPart part) {
super.setActiveEditor(part);
activeEditorPart = part;
// Switch to the new selection provider.
//
if (selectionProvider != null) {
selectionProvider.removeSelectionChangedListener(this);
}
if (part == null) {
selectionProvider = null;
}
else {
selectionProvider = part.getSite().getSelectionProvider();
selectionProvider.addSelectionChangedListener(this);
// Fake a selection changed event to update the menus.
//
if (selectionProvider.getSelection() != null) {
selectionChanged(new SelectionChangedEvent(selectionProvider, selectionProvider.getSelection()));
}
}
}
/**
* This implements {@link org.eclipse.jface.viewers.ISelectionChangedListener},
* handling {@link org.eclipse.jface.viewers.SelectionChangedEvent}s by querying for the children and siblings
* that can be added to the selected object and updating the menus accordingly.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void selectionChanged(SelectionChangedEvent event) {
IContributionItem[] items = generateMenuManager.getItems();
for (int i = 0, len = items.length; i < len; i++) items[i].update();
}
/**
* This populates the specified <code>manager</code> with {@link org.eclipse.jface.action.ActionContributionItem}s
* based on the {@link org.eclipse.jface.action.IAction}s contained in the <code>actions</code> collection,
* by inserting them before the specified contribution item <code>contributionID</code>.
* If <code>contributionID</code> is <code>null</code>, they are simply added.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected void populateManager(IContributionManager manager, Collection<? extends IAction> actions, String contributionID) {
if (actions != null) {
for (IAction action : actions) {
if (contributionID != null) {
manager.insertBefore(contributionID, action);
}
else {
manager.add(action);
}
}
}
}
/**
* This removes from the specified <code>manager</code> all {@link org.eclipse.jface.action.ActionContributionItem}s
* based on the {@link org.eclipse.jface.action.IAction}s contained in the <code>actions</code> collection.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected void depopulateManager(IContributionManager manager, Collection<? extends IAction> actions) {
if (actions != null) {
IContributionItem[] items = manager.getItems();
for (int i = 0; i < items.length; i++) {
// Look into SubContributionItems
//
IContributionItem contributionItem = items[i];
while (contributionItem instanceof SubContributionItem) {
contributionItem = ((SubContributionItem)contributionItem).getInnerItem();
}
// Delete the ActionContributionItems with matching action.
//
if (contributionItem instanceof ActionContributionItem) {
IAction action = ((ActionContributionItem)contributionItem).getAction();
if (actions.contains(action)) {
manager.remove(contributionItem);
}
}
}
}
}
/**
* This populates the pop-up menu before it appears.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void menuAboutToShow(IMenuManager menuManager) {
generateAllAction.setEnabled(generateAllAction.isEnabled());
generateTestsAction.setEnabled(generateTestsAction.isEnabled());
generateEditorAction.setEnabled(generateEditorAction.isEnabled());
generateEditAction.setEnabled(generateEditAction.isEnabled());
generateModelAction.setEnabled(generateModelAction.isEnabled());
super.menuAboutToShow(menuManager);
menuManager.insertBefore("edit", new Separator("generate-actions"));
menuManager.insertAfter("generate-actions", generateAllAction);
menuManager.insertAfter("generate-actions", generateTestsAction);
menuManager.insertAfter("generate-actions", generateEditorAction);
menuManager.insertAfter("generate-actions", generateEditAction);
menuManager.insertAfter("generate-actions", generateModelAction);
}
/**
* This inserts global actions before the "additions-end" separator.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
protected void addGlobalActions(IMenuManager menuManager) {
menuManager.insertAfter("additions-end", new Separator("ui-actions")); //$NON-NLS-1$ //$NON-NLS-2$
menuManager.insertAfter("ui-actions", showPropertiesViewAction); //$NON-NLS-1$
refreshViewerAction.setEnabled(refreshViewerAction.isEnabled());
menuManager.insertAfter("ui-actions", refreshViewerAction); //$NON-NLS-1$
super.addGlobalActions(menuManager);
}
/**
* This ensures that a delete action will clean up all references to deleted objects.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
protected boolean removeAllReferencesOnDelete() {
return true;
}
/**
* This gets the selection from the active editor.
*/
protected ISelection getActiveEditorSelection()
{
return activeEditorPart == null ? null :
((ISelectionProvider)activeEditorPart).getSelection();
}
/**
* This is the menu manager for the "Generate" menu.
*/
protected IMenuManager generateMenuManager;
protected IAction generateModelAction = new GenerateAction
(GenBaseGeneratorAdapter.MODEL_PROJECT_TYPE,
CodeGenEcorePlugin.INSTANCE.getString("_UI_ModelProject_name"),
GenModelEditPlugin.INSTANCE.getString("_UI_GenerateModel_menu_item"));
protected IAction generateEditAction = new GenerateAction
(GenBaseGeneratorAdapter.EDIT_PROJECT_TYPE,
CodeGenEcorePlugin.INSTANCE.getString("_UI_EditProject_name"),
GenModelEditPlugin.INSTANCE.getString("_UI_GenerateEdit_menu_item"));
protected IAction generateEditorAction = new GenerateAction
(GenBaseGeneratorAdapter.EDITOR_PROJECT_TYPE,
CodeGenEcorePlugin.INSTANCE.getString("_UI_EditorProject_name"),
GenModelEditPlugin.INSTANCE.getString("_UI_GenerateEditor_menu_item"));
protected IAction generateTestsAction = new GenerateAction
(GenBaseGeneratorAdapter.TESTS_PROJECT_TYPE ,
CodeGenEcorePlugin.INSTANCE.getString("_UI_TestsProject_name"),
GenModelEditPlugin.INSTANCE.getString("_UI_GenerateTests_menu_item"));
protected IAction generateAllAction = new GenerateAction
(new ProjectType[]
{
new ProjectType(GenBaseGeneratorAdapter.MODEL_PROJECT_TYPE, CodeGenEcorePlugin.INSTANCE.getString("_UI_ModelProject_name")),
new ProjectType(GenBaseGeneratorAdapter.EDIT_PROJECT_TYPE, CodeGenEcorePlugin.INSTANCE.getString("_UI_EditProject_name")),
new ProjectType(GenBaseGeneratorAdapter.EDITOR_PROJECT_TYPE, CodeGenEcorePlugin.INSTANCE.getString("_UI_EditorProject_name")),
new ProjectType(GenBaseGeneratorAdapter.TESTS_PROJECT_TYPE, CodeGenEcorePlugin.INSTANCE.getString("_UI_TestsProject_name"))
},
GenModelEditPlugin.INSTANCE.getString("_UI_GenerateAll_menu_item"));
/**
* This implements the "Generate..." actions.
*/
protected class GenerateAction extends Action
{
private final ProjectType[] projectTypes;
private Generator generator;
public GenerateAction(Object projectType, String projectTypeName, String text)
{
super(text);
this.projectTypes = new ProjectType[] { new ProjectType(projectType, projectTypeName) };
}
public GenerateAction(ProjectType[] projectTypes, String text)
{
super(text);
this.projectTypes = projectTypes;
}
@Override
public boolean isEnabled()
{
if (activeEditorPart instanceof LoopholeEditor)
{
generator = ((LoopholeEditor)activeEditorPart).getGenerator();
}
if (generator == null)
{
return false;
}
ISelection s = getActiveEditorSelection();
if (!(s instanceof IStructuredSelection))
{
return false;
}
IStructuredSelection ss = (IStructuredSelection)s;
if (ss.size() == 0)
{
return false;
}
for (Object object : ss.toList())
{
boolean canGenerateObject = false;
final Object unwrap;
if (object instanceof GenGapModel) {
unwrap = ((GenGapModel) object).getGenModel();
} else if (object instanceof GenGapPackage) {
unwrap = ((GenGapPackage) object).getGenPackage();
} else {
unwrap = object;
}
for (int i = 0; i < projectTypes.length; i++)
{
if (generator.canGenerate(unwrap, projectTypes[i].getType()))
{
canGenerateObject = true;
}
}
if (!canGenerateObject)
{
return false;
}
}
return true;
}
@Override
public void run()
{
generator.requestInitialize();
LoopholeGeneratorOperation operation =
new LoopholeGeneratorOperation(activeEditorPart.getSite().getShell());
operation.setRootDiagnosticMessage(getText());
GenModel genModel = null;
GenGapModel genGapModel = null;
Collection<?> selection = ((IStructuredSelection)getActiveEditorSelection()).toList();
for (Object object : selection)
{
for (int i = 0; i < projectTypes.length; i++)
{
GenBase genBase = null;
if (object instanceof GenGapModel)
{
genGapModel = (GenGapModel) object;
genModel = genGapModel.getGenModel();
genBase = genModel;
}
if (object instanceof GenGapPackage)
{
genBase = ((GenGapPackage) object).getGenPackage();
genGapModel = ((GenGapPackage) object).getGenGapModel();
genModel = genBase.getGenModel();
}
operation.addGeneratorAndArguments(generator, genBase, projectTypes[i].getType(), projectTypes[i].getName());
}
}
operation.setGenGapModel(genGapModel);
Set<IProject> projects = new HashSet<IProject>();
Set<IWorkingSet> workingSets = new HashSet<IWorkingSet>();
if (genModel != null)
{
IProject project = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(genModel.getModelDirectory())).getProject();
if (project != null)
{
IWorkbench workbench = PlatformUI.getWorkbench();
for (IWorkingSet workingSet : workbench.getWorkingSetManager().getAllWorkingSets())
{
IAdaptable[] elements = workingSet.getElements();
for (IAdaptable element : elements)
{
if (project.equals(element.getAdapter(IProject.class)))
{
workingSets.add(workingSet);
continue;
}
}
}
if (!workingSets.isEmpty())
{
for (int i = 0; i < projectTypes.length; i++)
{
Object projectType = projectTypes[i].getType();
if (GenBaseGeneratorAdapter.EDIT_PROJECT_TYPE.equals(projectType))
{
IProject editProject = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(genModel.getEditDirectory())).getProject();
if (!editProject.exists())
{
projects.add(editProject);
}
}
if (GenBaseGeneratorAdapter.EDITOR_PROJECT_TYPE.equals(projectType))
{
IProject editorProject = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(genModel.getEditorDirectory())).getProject();
if (!editorProject.exists())
{
projects.add(editorProject);
}
}
if (GenBaseGeneratorAdapter.TESTS_PROJECT_TYPE.equals(projectType))
{
IProject testsProject = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(genModel.getTestsDirectory())).getProject();
if (!testsProject.exists())
{
projects.add(testsProject);
}
}
}
}
}
}
// This runs the options, and shows progress.
// (It appears to be a bad thing to fork this onto another thread.)
//
try
{
new ProgressMonitorDialog(activeEditorPart.getSite().getShell()).run(true, true, operation);
if (!projects.isEmpty())
{
for (IWorkingSet workingSet : workingSets)
{
List<IAdaptable> elements = new ArrayList<IAdaptable>(Arrays.asList(workingSet.getElements()));
elements.addAll(projects);
workingSet.setElements(workingSet.adaptElements(elements.toArray(new IAdaptable[elements.size()])));
}
}
}
catch (Exception exception)
{
// Something went wrong that shouldn't.
//
GenModelEditPlugin.INSTANCE.log(exception);
}
}
}
protected static class ProjectType
{
protected Object type;
protected String name;
public ProjectType(Object type, String name)
{
this.type = type;
this.name = name;
}
public Object getType()
{
return type;
}
public String getName()
{
return name;
}
}
}